use serde::{Deserialize, Serialize};
use tauri::State;
use crate::services::video_service::{VideoService, ProcessParams, ExtractParams, BatchTask};
use crate::services::file_service::FileService;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConvertVideoRequest {
    pub input_path: String,
    pub output_path: String,
    pub format: String,
    pub quality: Option<u32>,
    pub bitrate: Option<u32>,
    pub resolution: Option<(u32, u32)>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExtractAudioRequest {
    pub video_path: String,
    pub audio_path: String,
    pub audio_format: String,
    pub bitrate: Option<u32>,
    pub sample_rate: Option<u32>,
}

#[tauri::command]
pub async fn convert_video(
    request: ConvertVideoRequest,
    video_service: State<'_, VideoService>,
) -> Result<serde_json::Value, String> {
    let params = ProcessParams {
        format: request.format,
        quality: request.quality,
        bitrate: request.bitrate,
        resolution: request.resolution,
    };
    
    match video_service.convert_video(request.input_path, request.output_path, params).await {
        Ok(result) => Ok(serde_json::to_value(result).map_err(|e| e.to_string())?),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub async fn extract_audio(
    request: ExtractAudioRequest,
    video_service: State<'_, VideoService>,
) -> Result<serde_json::Value, String> {
    let params = ExtractParams {
        audio_format: request.audio_format,
        bitrate: request.bitrate,
        sample_rate: request.sample_rate,
    };
    
    match video_service.extract_audio(request.video_path, request.audio_path, params).await {
        Ok(result) => Ok(serde_json::to_value(result).map_err(|e| e.to_string())?),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub async fn get_video_info(
    file_path: String,
    video_service: State<'_, VideoService>,
) -> Result<serde_json::Value, String> {
    match video_service.get_video_info(file_path).await {
        Ok(info) => Ok(serde_json::to_value(info).map_err(|e| e.to_string())?),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub async fn batch_process_videos(
    tasks: Vec<BatchTask>,
    video_service: State<'_, VideoService>,
) -> Result<serde_json::Value, String> {
    match video_service.batch_process(tasks).await {
        Ok(result) => Ok(serde_json::to_value(result).map_err(|e| e.to_string())?),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub fn get_supported_video_formats(
    video_service: State<'_, VideoService>,
) -> Result<serde_json::Value, String> {
    let formats = video_service.get_supported_video_formats();
    Ok(serde_json::to_value(formats).map_err(|e| e.to_string())?)
}

#[tauri::command]
pub fn get_supported_audio_formats(
    video_service: State<'_, VideoService>,
) -> Result<serde_json::Value, String> {
    let formats = video_service.get_supported_audio_formats();
    Ok(serde_json::to_value(formats).map_err(|e| e.to_string())?)
}

#[tauri::command]
pub fn get_active_tasks(
    video_service: State<'_, VideoService>,
) -> Result<serde_json::Value, String> {
    let tasks = video_service.get_active_tasks();
    Ok(serde_json::to_value(tasks).map_err(|e| e.to_string())?)
}

#[tauri::command]
pub fn cancel_task(
    task_id: String,
    video_service: State<'_, VideoService>,
) -> Result<bool, String> {
    Ok(video_service.cancel_task(&task_id))
}

#[tauri::command]
pub async fn select_video_file(
    file_service: State<'_, FileService>,
) -> Result<Option<String>, String> {
    let filters = FileService::get_video_file_filters();
    
    match file_service.select_file(Some("选择视频文件"), Some(filters), None).await {
        Ok(path) => Ok(path),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub async fn select_video_files(
    file_service: State<'_, FileService>,
) -> Result<Vec<String>, String> {
    let filters = FileService::get_video_file_filters();
    
    match file_service.select_files(Some("选择视频文件"), Some(filters), None).await {
        Ok(paths) => Ok(paths),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub async fn select_output_directory(
    file_service: State<'_, FileService>,
) -> Result<Option<String>, String> {
    match file_service.select_directory(Some("选择输出目录"), None).await {
        Ok(path) => Ok(path),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub async fn create_output_path(
    input_path: String,
    output_format: String,
    output_dir: Option<String>,
    suffix: Option<String>,
    file_service: State<'_, FileService>,
) -> Result<String, String> {
    match file_service.create_output_path(
        &input_path,
        &output_format,
        output_dir.as_deref(),
        suffix.as_deref(),
    ).await {
        Ok(path) => Ok(path),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub async fn validate_video_file(
    file_path: String,
    file_service: State<'_, FileService>,
) -> Result<bool, String> {
    match file_service.validate_video_file(&file_path) {
        Ok(_) => Ok(true),
        Err(e) => Err(e.to_string()),
    }
}

#[tauri::command]
pub fn get_ffmpeg_info(
    video_service: State<'_, VideoService>,
) -> Result<serde_json::Value, String> {
    let ffmpeg_path = video_service.get_ffmpeg_path();
    let ffmpeg_version = video_service.get_ffmpeg_version()
        .unwrap_or_else(|_| "Unknown".to_string());

    let info = serde_json::json!({
        "path": ffmpeg_path,
        "version": ffmpeg_version,
        "status": "available"
    });

    Ok(info)
}